import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
import java.util.StringTokenizer;

import com.dp1.deliversoft.algorithm.Grasp;
import com.dp1.deliversoft.entidad.Constantes;
import com.dp1.deliversoft.entidad.Mapa;
import com.dp1.deliversoft.entidad.Pedido;
import com.dp1.deliversoft.entidad.Ruta;
import com.dp1.deliversoft.entidad.Vehiculo;

public class Main {

	ArrayList<Pedido> pedidos;
	Mapa mapita;
	

	public static void main(String[] args) {
		int n = 5;
		double ct=0;
		Ruta S;
		
		/*ESTE BLQOUE SE PUSO PARA PROBAR EL GRASP: CARLOS SAENZ*/
		
		//CARGAR MAPA
		Mapa mapita = new Mapa(100, 100);
		mapita.colocarAlmacen(0, 0);
		//CARGAR PEDIDOS
		ArrayList<Pedido> pedidos=crearPedidos();
		muestraPedidos(pedidos);
		
		//CARGAR VEHICULOS
		ArrayList<Vehiculo> vehiculos=GeneraVehiculos();
		
		//CALCULAR SALIDA
		ArrayList<Ruta> rpta=Grasp.GraspPrincipal(pedidos, mapita, vehiculos);
		
		//MOSTRAR
		System.out.println("IMPRIMIENDO SALIDA");
		for (int i=0;i<rpta.size();i++) 
			{
				muestraRuta(rpta.get(i));
				ct=ct+rpta.get(i).getCostoRuta();
			}
		System.out.println("Costo Operacio = "+ct);
		
		/* -------------------FIN BLOQUE CARLOS------------------------*/


		/*
		// Se crea el mapa
		Mapa mapita = new Mapa(45, 40);
		// Se inicializan las coordenadas del mapa
		mapita.colocarAlmacen(30, 30);
		// Crea N pedidos con coordenadas semi aleatorias
		//ArrayList<Pedido> p = crearPedidos(20);
		ArrayList<Pedido> p = crearPedidos2(20, mapita);
		TablaRuteoAux tabAux = new TablaRuteoAux(p, mapita);
		//tabAux.dibujar(p);
		rutear rt = new rutear();
		S = rt.GeneraRuta(25, p, false, mapita, tabAux);
		System.out.println("Ola q ase");
		
		
		
		for (int i = 0; i < S.getPedidos().size(); i++) {
			try
			{
				//System.out.println("bien"+i+"x: "+S.getPedidos().get(i).getPosX()+"y: "+S.getPedidos().get(i).getPosY());
				mapita.colocarCasa(S.getPedidos().get(i).getPosX()+1, S
						.getPedidos().get(i).getPosY()+1, "" + i);
			}
			catch (Exception e)
			{
				System.out.println("error"+i+"x: "+S.getPedidos().get(i).getPosX()+"y: "+S.getPedidos().get(i).getPosY());
			}
			
			// System.out.println("pedidos.add(new Pedido("+(S.getPedidos().get(i-1).getPosX()+1)+","+(S.getPedidos().get(i-1).getPosY()+1)+", 1, 1, 1));");
			
		}
		mapita.dibujarMapa();
		
		for (int i = 0; i < S.getPedidos().size(); i++) {
			try
			{
				//System.out.println("bien"+i+"x: "+S.getPedidos().get(i).getPosX()+"y: "+S.getPedidos().get(i).getPosY());
				mapita.colocarCasa(S.getPedidos().get(i).getPosX()+1, S
						.getPedidos().get(i).getPosY()+1, ".");
			}
			catch (Exception e)
			{
				System.out.println("error"+i+"x: "+S.getPedidos().get(i).getPosX()+"y: "+S.getPedidos().get(i).getPosY());
			}
			
			// System.out.println("pedidos.add(new Pedido("+(S.getPedidos().get(i-1).getPosX()+1)+","+(S.getPedidos().get(i-1).getPosY()+1)+", 1, 1, 1));");
		}
		
		
		
		//zonas = rt.ParticionarEnZonas(zonas, S);
		ArrayList<Ruta> zonas = rt.particionarRutaSimp(S);	
		for (Ruta ruta : zonas)
		{
			//ruta.setPedidos(rt.GeneraRuta(20, ruta.getPedidos(), false, mapita, tabAux).getPedidos());
			rt.reiniciarEstados(ruta.getPedidos());
			ruta = Grasp2.GraspPrincipal(ruta.getPedidos(), mapita);
			
			/*for (int i = 0; i < ruta.getPedidos().size(); i++) {
				try
				{
					//System.out.println("bien"+i+"x: "+S.getPedidos().get(i).getPosX()+"y: "+S.getPedidos().get(i).getPosY());
					mapita.colocarCasa(ruta.getPedidos().get(i).getPosX()+1, ruta
							.getPedidos().get(i).getPosY()+1, "" + i);
				}
				catch (Exception e)
				{
					System.out.println("error"+i+"x: "+ruta.getPedidos().get(i).getPosX()+"y: "+ruta.getPedidos().get(i).getPosY());
				}
				
				// System.out.println("pedidos.add(new Pedido("+(S.getPedidos().get(i-1).getPosX()+1)+","+(S.getPedidos().get(i-1).getPosY()+1)+", 1, 1, 1));");
			}*/
			/*mapita.dibujarMapa();
			
			for (int i = 0; i < ruta.getPedidos().size(); i++) {
				try
				{
					//System.out.println("bien"+i+"x: "+S.getPedidos().get(i).getPosX()+"y: "+S.getPedidos().get(i).getPosY());
					mapita.colocarCasa(ruta.getPedidos().get(i).getPosX()+1, ruta
							.getPedidos().get(i).getPosY()+1, ".");
				}
				catch (Exception e)
				{
					System.out.println("error"+i+"x: "+ruta.getPedidos().get(i).getPosX()+"y: "+ruta.getPedidos().get(i).getPosY());
				}
				
				// System.out.println("pedidos.add(new Pedido("+(S.getPedidos().get(i-1).getPosX()+1)+","+(S.getPedidos().get(i-1).getPosY()+1)+", 1, 1, 1));");
			}*/
		

		
		
		// Se muestra el mapa

		// mapita.dibujarMapa();

		// Crea N pedidos con coordenadas semi aleatorias
		// ArrayList<Pedido> p = crearPedidos(20);

		// Crea pedidos con un for
		 
		//
		// ArrayList<Pedido> p = crearPedidos(10);
		// mapita.dibujarMapa();

		// ArrayList<Pedido> p = new ArrayList<Pedido>();
		// hardcodearPedidos(p);
		// p = crearPedidos2(20, mapita);
		// TablaRuteoAux tabAux = new TablaRuteoAux(p,mapita);
		// Ruta S = rt.GeneraRuta(5, p,
		// false, mapita, tabAux);

		/*System.out.println("Ola q ase");
		for (int i = 1; i < S.getPedidos().size(); i++) {

			mapita.colocarCasa(S.getPedidos().get(i - 1).getPosX() + 1, S
					.getPedidos().get(i - 1).getPosY() + 1, "" + i);
			// System.out.println("pedidos.add(new Pedido("+(S.getPedidos().get(i-1).getPosX()+1)+","+(S.getPedidos().get(i-1).getPosY()+1)+", 1, 1, 1));");
		}
		System.out.println("Iniciando el grasp");*/
		// Ruta S=Grasp.GraspPrincipal(p, mapita);
		// mapita.dibujarMapa();
		
		// System.out.println(S.getPedidos().size());
		// System.out.println(S.getCostoRuta());
		//

		// mapita.dibujarMapa();
		// paraProbarGrasp();
		// codCarlos();

		// System.out.println("costo "+r.getCostoRuta());

		// Inicializa la tabla de feromonas y visibilidad
		// TablaRuteoAux tabAux = new TablaRuteoAux(pedidos, mapita);
		// tabAux.dibujar(pedidos);

		// Mapa mapita = new Mapa(150, 100);
		// mapita.colocarAlmacen(0, 0);
		// mapita.dibujarMapa();
		// ArrayList<Pedido> pedidos = crearPedidos(10);

		// ArrayList<Vehiculo> vehiculos=GeneraVehiculos();
		// esto solo es para probar directamente el grasp
		// Ruta r;
		// System.out.println("Iniciando el grasp");
		// r=Grasp.GraspPrincipal(pedidos, mapita);

		// muestraRuta(r);

		// rutear ru= new rutear();
		// ru.setListaVehiculos(vehiculos);
		// ArrayList<Ruta> rutas=ru.asignarVehiculo(r);
		//
		// rutear ru= new rutear(); ru.setListaVehiculos(vehiculos);
		 // ru.setMapa(mapita); ArrayList<Ruta> rutas=ru.asignarVehiculo(r);
		 //

		//
		 // if (rutas==null) System.out.println("la lista de rutas es vacia");
		//else
		// 
		//if (rutas==null) System.out.println("la lista de rutas es vacia");
		//else
		 
		// System.out.println("cantidad de vehiculos "+rutas.size()); for (int
		// i=0;i<rutas.size();i++) { //if (rutas.get(i)==null)
		// System.out.println("rutas invalidas"); muestraRuta(rutas.get(i)); }
		//
		
	}

	public static void hardcodearPedidos(ArrayList<Pedido> pedidos) {
		pedidos.add(new Pedido(26, 2, 1, 1, 1));
		pedidos.add(new Pedido(26, 3, 1, 1, 1));
		pedidos.add(new Pedido(26, 9, 1, 1, 1));
		/*
		 * pedidos.add(new Pedido(31,11, 1, 1, 1)); pedidos.add(new Pedido(35,8,
		 * 1, 1, 1)); pedidos.add(new Pedido(34,7, 1, 1, 1)); pedidos.add(new
		 * Pedido(34,2, 1, 1, 1)); pedidos.add(new Pedido(34,16, 1, 1, 1));
		 * pedidos.add(new Pedido(34,30, 1, 1, 1)); pedidos.add(new
		 * Pedido(30,31, 1, 1, 1)); pedidos.add(new Pedido(22,31, 1, 1, 1));
		 * pedidos.add(new Pedido(20,31, 1, 1, 1)); pedidos.add(new
		 * Pedido(20,35, 1, 1, 1)); pedidos.add(new Pedido(17,29, 1, 1, 1));
		 * pedidos.add(new Pedido(11,23, 1, 1, 1)); pedidos.add(new Pedido(9,23,
		 * 1, 1, 1)); pedidos.add(new Pedido(8,22, 1, 1, 1)); pedidos.add(new
		 * Pedido(9,20, 1, 1, 1)); pedidos.add(new Pedido(23,22, 1, 1, 1));
		 */
	}

	public static boolean zonasCompletas(ArrayList<Ruta> zonas, ArrayList<Ruta> zonasListas, ArrayList<Ruta> zonasTodavia )
	{
		boolean res = true;
		Iterator<Ruta> it;
		Ruta ruta;
		int tamanio = zonas.size(); 
		
		while (tamanio>0)
		{
			it=zonas.iterator();
			ruta = it.next();
			if (ruta.getPedidos().size()<=25) //entra en un vehiculo
			{
				zonas.remove(ruta);
				zonasListas.add(ruta); //y ademas asignarle un vehiculo
			}
			else
			{
				zonas.remove(ruta);
				zonasTodavia.add(ruta);
				res = false;
			}
			tamanio = zonas.size(); 
		}
		
		return res;
		
	}
	
	public static void paraProbarGrasp() {
		// esto solo es para probar directamente el grasp
		Ruta r;
		System.out.println("Iniciando el grasp");
		// r=Grasp.GraspPrincipal(pedidos, mapita);
		// generadorRuta.inicializarVehiculos();
		// r = generadorRuta.rutearPedidos(mapita, pedidos, tabAux).get(0);
	}

	public static void codCarlos() {
		// creamos lista de vehiculos
		ArrayList<Vehiculo> vehiculos = GeneraVehiculos();
	}


/*	public static void paraProbarGrasp() {
		// esto solo es para probar directamente el grasp
		Ruta r;
		//System.out.println("Iniciando el grasp");
		
		for (int i=0;i<50;i++)
		{
			Date d = new Date();
			long ti,tf;
		
			
			
			mapita = new Mapa(150, 100);
			mapita.colocarAlmacen(0, 0);
			pedidos = crearPedidos(10);
			ti=d.getTime();
			Calendar ahora1 = Calendar.getInstance();
			long tiempo1 = ahora1.getTimeInMillis();
			
			r=Grasp.GraspPrincipal(pedidos, mapita);
			
			Calendar ahora2 = Calendar.getInstance();
			long tiempo2 = ahora2.getTimeInMillis();
			
			tf=d.getTime();
			muestraRuta(r);
			System.out.println(tiempo2 - tiempo1);
			
		}
		
}*/

	public static void muestraRuta(Ruta r) {
		ArrayList<Pedido> salida;
		salida = r.getPedidos();
		System.out.println("tipo de vehiculo "+ r.getVehiculo().getIdVehiculo()+" capacidad "+r.getVehiculo().getCapCarga()+" paquetes "+r.getVehiculo().getCarga());
		System.out.println("horas de retraso "+r.getHorasRetraso());
		muestraPedidos(salida);
		System.out.println("costo " + r.getCostoRuta());
	}
	
	public static void muestraPedidos(ArrayList<Pedido> salida)
	{
		for (int i = 0; i < salida.size(); i++) {
			System.out.println("codigo " + salida.get(i).getIdCliente() + " "
					+ salida.get(i).getPosX() + "," + salida.get(i).getPosY()
					+ "," + salida.get(i).getPlazo() + ","
					+ salida.get(i).getCantPaquetes());
		}
	}

	public static ArrayList<Pedido> crearPedidos() {

		int i = 0;
		ArrayList<Pedido> pedidos = new ArrayList<Pedido>();
		String cad, s1, s2, s3, s4;
		try {
			BufferedReader Entrada = new BufferedReader(new FileReader(
					"C:/pedidos.txt"));

			while ((cad = Entrada.readLine()) != null) {
				// System.out.println(""+1);
				StringTokenizer st = new StringTokenizer(cad, ",");

				s1 = (String) st.nextToken();
				s2 = (String) st.nextToken();
				s3 = (String) st.nextToken();
				s4 = (String) st.nextToken();
				pedidos.add(new Pedido(Integer.parseInt(s1), Integer
						.parseInt(s2), Integer.parseInt(s4), Integer
						.parseInt(s3), i));
				i++;
				
				//if (i==10) break;
			}

		} catch (Exception e) {

		}

		return pedidos;
	}

	public static ArrayList<Pedido> crearPedidos2(int n, Mapa mapita) {
		Random rn = new Random();
		Random rp = new Random();
		int max = 35, t, i = 0;
		ArrayList<Pedido> pedidos = new ArrayList<Pedido>();
		int x;
		int y;

		for (int m = 0; m < n; m++) {
			x = rn.nextInt(max);
			y = rp.nextInt(max);
			// mapita.colocarCasa(x, y, 'd');
			pedidos.add(new Pedido(x, y, 4, 1, 1));
		}
		return pedidos;
	}

	public static ArrayList<Vehiculo> GeneraVehiculos() {
		ArrayList<Vehiculo> v = new ArrayList<Vehiculo>();
		int i = 0;

		// creamos motos
		for (i = 0; i < Constantes.cantAuto; i++)
			v.add(new Vehiculo(i, Constantes.tipoAuto,
					Constantes.estVehiculoDisponible));

		// creamos autos
		for (int j = 0; j < Constantes.cantMoto; j++)
			v.add(new Vehiculo(i + j, Constantes.tipoMoto,
					Constantes.estVehiculoDisponible));

		return v;
	}
	
	public void otroMetodoPartirZonas()
	{
		/*ArrayList<Ruta> zonasListas = new ArrayList<Ruta>();
		ArrayList<Ruta> zonasPendientes = new ArrayList<Ruta>();
		ArrayList<Ruta> zonasInicial = new ArrayList<Ruta>();
		ArrayList<Ruta> l = new ArrayList<Ruta>();
		ArrayList<Ruta> lRHorizontal = new ArrayList<Ruta>();
		ArrayList<Ruta> lRVertical = new ArrayList<Ruta>();
		
		boolean estanZonasCompletas = true;
		zonasInicial.add(S);
		
		if (S.cantPaquetes()>25){
			estanZonasCompletas = zonasCompletas(zonasInicial, zonasListas, zonasPendientes);
		}
		else 
		{
			zonasListas.add(S);
		}
		
		ArrayList<Ruta> zonas1, zonas2;
		ArrayList<Integer> centro;
		Vehiculo vehiculo;

		int cx, cy;
		int costoHorizontal, costoVertical;
		Ruta S1, S2;
		
		Iterator<Ruta> it;
		Ruta r;
		
		while (zonasPendientes.size()>0)
		{
			it=zonasPendientes.iterator();
			r = it.next();
			while (!estanZonasCompletas){
				l.clear();
				lRHorizontal.clear();
				lRVertical.clear();
				centro = r.calcularCentroX(mapita);
				cx = centro.get(0);
				cy = centro.get(1);
				
				
				lRHorizontal = rt.partirRuta2(S, cx, cy, "H");
				costoHorizontal = (int) (lRHorizontal.get(0).getCostoRuta() + lRHorizontal
						.get(1).getCostoRuta()); // Falta calcular El costo de
													// las
				// Rutas en Horizontal

				
				lRVertical = rt.partirRuta2(S, cx, cy, "V");
				costoVertical = (int) (lRVertical.get(0).getCostoRuta() + lRVertical
						.get(1).getCostoRuta());

				if (costoHorizontal >= costoVertical) {
					S1 = lRHorizontal.get(0);
					S2 = lRHorizontal.get(1);
				} else {
					S1 = lRVertical.get(0);
					S2 = lRVertical.get(1);
				}
				l.add(S1);
				l.add(S2);
				zonasPendientes.remove(r);
				estanZonasCompletas = zonasCompletas(l, zonasListas, zonasPendientes);
			
			}
		}
		
		for (Ruta ruta : zonasListas)
		{
			for (int i = 0; i < ruta.getPedidos().size(); i++) {
				try
				{
					//System.out.println("bien"+i+"x: "+S.getPedidos().get(i).getPosX()+"y: "+S.getPedidos().get(i).getPosY());
					mapita.colocarCasa(ruta.getPedidos().get(i).getPosX()+1, ruta
							.getPedidos().get(i).getPosY()+1, "" + i);
				}
				catch (Exception e)
				{
					System.out.println("error"+i+"x: "+ruta.getPedidos().get(i).getPosX()+"y: "+ruta.getPedidos().get(i).getPosY());
				}
				
				// System.out.println("pedidos.add(new Pedido("+(S.getPedidos().get(i-1).getPosX()+1)+","+(S.getPedidos().get(i-1).getPosY()+1)+", 1, 1, 1));");
			}
		}
		
		*/
	}
}

